package com.blogspot.javagamexyz.gamexyz.screens;

import com.artemis.Component;
import com.artemis.Entity;
import com.artemis.World;
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.graphics.OrthographicCamera;
import com.badlogic.gdx.graphics.g2d.SpriteBatch;
import com.badlogic.gdx.math.MathUtils;
import com.badlogic.gdx.scenes.scene2d.Stage;
import com.badlogic.gdx.scenes.scene2d.ui.Label;
import com.badlogic.gdx.scenes.scene2d.ui.Skin;
import com.badlogic.gdx.scenes.scene2d.ui.Table;
import com.badlogic.gdx.utils.Array;
import com.blogspot.javagamexyz.gamexyz.EntityFactory;
import com.blogspot.javagamexyz.gamexyz.GameXYZ;
import com.blogspot.javagamexyz.gamexyz.PlayerManager2;
import com.blogspot.javagamexyz.gamexyz.abilities.Action2;
import com.blogspot.javagamexyz.gamexyz.components.AI;
import com.blogspot.javagamexyz.gamexyz.components.Stats;
import com.blogspot.javagamexyz.gamexyz.custom.Label2;
import com.blogspot.javagamexyz.gamexyz.custom.Pair;
import com.blogspot.javagamexyz.gamexyz.maps.GameMap;
import com.blogspot.javagamexyz.gamexyz.maps.MapTools;
import com.blogspot.javagamexyz.gamexyz.renderers.MapHighlighter;
import com.blogspot.javagamexyz.gamexyz.renderers.MapRenderer;
import com.blogspot.javagamexyz.gamexyz.screens.control.overworld.InputManager;
import com.blogspot.javagamexyz.gamexyz.systems.AISystem;
import com.blogspot.javagamexyz.gamexyz.systems.CameraMovementSystem;
import com.blogspot.javagamexyz.gamexyz.systems.DamageSystem;
import com.blogspot.javagamexyz.gamexyz.systems.FadingMessageRenderSystem;
import com.blogspot.javagamexyz.gamexyz.systems.HudRenderSystem;
import com.blogspot.javagamexyz.gamexyz.systems.MovementSystem;
import com.blogspot.javagamexyz.gamexyz.systems.SpriteRenderSystem;
import com.blogspot.javagamexyz.gamexyz.systems.TurnManagementSystem;
import com.blogspot.javagamexyz.gamexyz.ui.HUDManager;
import com.blogspot.javagamexyz.gamexyz.ui.StatsHUD;

public class OverworldScreen extends AbstractScreen {
	
	public static GameMap gameMap;
	private OrthographicCamera hudCam;
	
	float timer;
	
	//TODO get rid of turn management system, that's only for combat
	private SpriteRenderSystem spriteRenderSystem;
	private HudRenderSystem hudRenderSystem;
	private FadingMessageRenderSystem fadingMessageRenderSystem;
	private TurnManagementSystem turnManagementSystem;
	
	private MapRenderer mapRenderer;
	private MapHighlighter mapHighlighter;
	
	public int activeEntity;
	public Pair activeEntityCell;
	public Array<Pair> highlightedCells;
	public boolean renderMap;
	
	//TODO these will need to be refactored
	public boolean renderMovementRange;
	public boolean renderAttackRange;
	public boolean renderHighlighter;
	
	public InputManager inputManager;
	public Stage stage;
	
	
	public int cursor;
	
	//TODO also get rid of this stuff
	public Array<Integer> unitOrder;
	public boolean moved = false;
	public boolean attacked = false;
	
	public CameraMovementSystem cameraMovementSystem; 
	private boolean firstShow = true;
	
	public Action2 currentAction;
	
	//New UI stuff - may be moved to StatsHUD class
	//public Stage hudStage;	//moved to input manager to keep everything nice and contained... let's see how it goes
	//HUDManager hud;

	
	public OverworldScreen(GameXYZ game, SpriteBatch batch, World world) {
		super(game,world,batch);

		timer = 0f;
		
		cameraMovementSystem = new CameraMovementSystem(camera);
		activeEntityCell = new Pair(0,0);
    	gameMap  = new GameMap();
    	
    	stage = new Stage();
    	
    	inputManager = new InputManager(camera, world, this, stage, gameMap);	//TODO since it has the main stage, the hudStage functions will not work
    	
    	//TODO add UI stuff here and maybe move it to a new class which will manage the UI accross all Screens
    	
    	//hudStage = new Stage();
    	//statsHud = new StatsHUD(hudStage);
    	//hud = new HUDManager(hudStage, inputManager);    	
    	
    	
    	unitOrder = new Array<Integer>();
    	setupWorld();
    	fillWorldWithEntities();

    	renderMap = true;
    	renderMovementRange = false;
    	renderAttackRange = false;
    	renderHighlighter = false;	
    	
	}
	
	@Override
	public void render(float delta) {	
		super.render(delta);
		
		if (firstShow) {
			cameraMovementSystem.move(activeEntityCell.x, activeEntityCell.y);
			firstShow = false;
		}
		
		if (renderMap) {
			mapRenderer.render();
			spriteRenderSystem.process();
		}
		
		if (renderHighlighter) {
			mapHighlighter.render(highlightedCells);
		}
		
		fadingMessageRenderSystem.process();
		
		stage.act(delta);
		stage.draw();
		//hudStage.act(delta);	//since everything is on one stage now this shouldn't be needed...
		//hudStage.draw();
		
		//hudRenderSystem.process();
		
		cameraMovementSystem.process(delta);
	}

	@Override
	public void show() {
		
	}
	
	@Override
	public void resize(int width, int height) {
		super.resize(width, height);
		hudCam.setToOrtho(false, width, height);
		stage.setViewport(width, height, true);
		//hudStage.setViewport(width, height, true);	//not needed
	}

	@Override
	public void hide() {
		//Auto-generated method stub
		
	}

	@Override
	public void pause() {
		//Auto-generated method stub
		
	}

	@Override
	public void resume() {
		//Auto-generated method stub
		
	}

	@Override
	public void dispose() {
		//Auto-generated method stub
		world.deleteSystem(hudRenderSystem);
		world.deleteSystem(spriteRenderSystem);
		world.deleteSystem(world.getSystem(MovementSystem.class));
		stage.dispose();
		//hudStage.dispose();
	}
	
	private void setupWorld() {
		
		world.setManager(new PlayerManager2());
		
		hudCam = new OrthographicCamera();	//this isn't used anymore
    	
    	mapRenderer = new MapRenderer(camera,batch,gameMap.map);
    	mapHighlighter = new MapHighlighter(camera, batch);
    	
    	world.setSystem(new MovementSystem(gameMap,this));
    	world.setSystem(new DamageSystem(gameMap));	//TODO get rid of this
    	world.setSystem(new AISystem(this, gameMap)); //TODO get rid of this
    	spriteRenderSystem = world.setSystem(new SpriteRenderSystem(camera,batch), true);
    	hudRenderSystem = world.setSystem(new HudRenderSystem(hudCam, batch),true);	//this isn't used anymore
    	fadingMessageRenderSystem = world.setSystem(new FadingMessageRenderSystem(camera,batch),true);
    	turnManagementSystem = world.setSystem(new TurnManagementSystem(unitOrder), true);	//TODO get rid of this
    	
    	world.initialize();
    	System.out.println("The world is initialized");
    	
	}
	
	
	private void fillWorldWithEntities() {
		/*
		int x, y;
		    	for (int i=0; i<1; i++) {
    		do {
    			x = MathUtils.random(MapTools.width()-1);
    			y = MathUtils.random(MapTools.height()-1);
    		} while (gameMap.cellOccupied(x, y) || (gameMap.map[x][y]==0) || (gameMap.map[x][y]==1));
    		EntityFactory.createBlue(world,x,y,gameMap).addToWorld();
    		
    		do {
    			x = MathUtils.random(MapTools.width()-1);
    			y = MathUtils.random(MapTools.height()-1);
    		} while (gameMap.cellOccupied(x, y) || (gameMap.map[x][y]==0) || (gameMap.map[x][y]==1));
    		EntityFactory.createRed(world,x,y,gameMap).addToWorld();
    		
    		do {
    			x = MathUtils.random(MapTools.width()-1);
    			y = MathUtils.random(MapTools.height()-1);
    		} while (gameMap.cellOccupied(x, y) || (gameMap.map[x][y]==0) || (gameMap.map[x][y]==1));
    		
    		EntityFactory.createNPC(world, x, y, gameMap).addToWorld();
    	}
    	*/
    	
		EntityFactory.createNeutralAgressive(world, 5, 5, gameMap).addToWorld();
		EntityFactory.createPlayerChar(world, 10, 10, gameMap).addToWorld();
		
    	Entity e = EntityFactory.createCursor(world);
    	cursor = e.getId();
    	e.addToWorld();
    	
    	// You have to process the world once to get all the entities loaded up with
    	// the "Stats" component - I'm not sure why, but if you don't, the bag of entities
    	// that turnManagementSystem gets is empty?
    	world.process();
    	// Running processTurn() once here initializes the unit order, and selects the first
    	// entity to go
    	processTurn();
	}
	
	public void processTurn() {
		//TODO don't bother with this stuff outside of combat		
		turnManagementSystem.process();	//I'm guessing this calls processEntities in some way
		activeEntity = unitOrder.get(0);	//get the entity at the top of the order list, or at the least the ID...?
		activeEntityCell = gameMap.getCoordinatesFor(activeEntity);
		
		//Update HUD
		//hud.process(world.getEntity(activeEntity).getComponent(Stats.class));	//moved to input manager... I dunno hopefully this works now
		inputManager.hudManager.process(world.getEntity(activeEntity).getComponent(Stats.class));
		
		// As long as that entity has a location, focus the camera on them
		if (activeEntityCell != null) {
			cameraMovementSystem.move(activeEntityCell.x, activeEntityCell.y);
		}		

		// Try to get the next entity's AI
		AI ai = world.getEntity(activeEntity).getComponent(AI.class);
		
		// If they don't have AI, give control to the human player
		if (ai == null) inputManager.setEnabled(true);
		
		// Otherwise take control away, and begin that AI's processing.
		else {
			inputManager.setEnabled(false);
			ai.begin();
		}
	}
	
	public void startMoving(int x, int y) {
		cameraMovementSystem.move(x, y);
		//Gdx.input.setInputProcessor(null);
	}
	
	public void stopMoving() {
	//	Gdx.input.setInputProcessor(inputSystem);
	}
	
	public boolean cameraMoving() {
		return cameraMovementSystem.active;
	}
	
	public void setHighlightColor(float r, float g, float b, float a) {
		mapHighlighter.setColor(r,g,b,a);
	}
	
	public void highlightMovementRange() {
		renderHighlighter = true;
		setHighlightColor(0f, 0f, 0.2f, 0.3f);
	}
	
	public void highlightAttackRange() {
		renderHighlighter = true;
		setHighlightColor(0.5f, 0f, 0f, 0.3f);
	}
	
	public void addComponent(Component component, int entityId) {
		if (entityId < 0) return;
		Entity e = world.getEntity(entityId);
		e.addComponent(component);
		e.changedInWorld();
	}
}
